package com.jfinal.weixin.lbs.util;

import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.weixin.lbs.model.*;
import com.jfinal.weixin.sdk.utils.HttpUtils;
import com.jfinal.weixin.sdk.utils.JsonUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Jack.Zhou on 12/18/2015.
 */
public class BaiduLBSUtil {


    public static final String createGEOTableUrl = "http://api.map.baidu.com/geodata/v3/geotable/create";
    public static final String listGEOTableUrl = "http://api.map.baidu.com/geodata/v3/geotable/list";
    public static final String createGEOColumnUrl = "http://api.map.baidu.com/geodata/v3/column/create";
    public static final String createGEODataUrl = "http://api.map.baidu.com/geodata/v3/poi/create";
    public static final String listGEODataUrl = "http://api.map.baidu.com/geodata/v3/poi/list";
    public static final String revertGEOLocation = "http://api.map.baidu.com/geocoder/v2/";
    public static final String updateGEOColumnUrl = "http://api.map.baidu.com/geodata/v3/poi/update";
    public static final int COLUMN_TYPE_INT64 = 1;
    public static final int COLUMN_TYPE_DOUBLE = 2;
    public static final int COLUMN_TYPE_STRING = 3;
    public static final int COLUMN_TYPE_URL = 4;
    public static final int COORD_TYPE_GPS = 1;
    public static final int COORD_TYPE_GOV = 2;
    public static final int COORD_TYPE_BD = 3;
    public static final int CHORD_TYPE_BD_ENCRYPT = 4;
    public static final String CHARSET = "UTF-8";
    public static final String AK = "baiduAK";
    public static final String WECHAT_TABLE_NAME = "WeChatUserInfo";


    public static String getTableId(String tableName) {
        ListGEOTable info = new ListGEOTable();
        info.setAk(PropKit.get(AK));
        info.setName(tableName);
        JSONObject result = BaiduLBSUtil.listGEOTable(info);
        return result.getJSONArray("geotables").getJSONObject(0).getString("id");
    }

    /**
     * @param table 表信息
     * @return createTableId
     */
    public static String createGEOTable(CreateGEOTable table) {
        String jsonResult = HttpUtils.post(createGEOTableUrl, objectToURlFormat(table));
        JSONObject result = JsonUtils.parse(jsonResult, JSONObject.class);
        if (result.getInteger("status") != 0) {
            throw new RuntimeException(result.toString());
        }
        return result.getString("id");
    }

    /**
     * @param listBean 表信息
     * @return JSONObject
     */
    public static JSONObject listGEOTable(ListGEOTable listBean) {
        String jsonResult = HttpUtils.get(listGEOTableUrl + "?" + objectToURlFormat(listBean));
        JSONObject result = JsonUtils.parse(jsonResult, JSONObject.class);
        if (result.getInteger("status") != 0) {
            throw new RuntimeException(result.toString());
        }
        return result;
    }

    /**
     * @param columnInfo 列信息
     * @return createColumnId
     */
    public static String createGEOColumn(CreateGEOColumn columnInfo) {
        String jsonResult = HttpUtils.post(createGEOColumnUrl, objectToURlFormat(columnInfo));
        JSONObject result = JsonUtils.parse(jsonResult, JSONObject.class);
        if (result.getInteger("status") != 0) {
            throw new RuntimeException(result.toString());
        }
        return result.getString("id");
    }

    /**
     * @param data         基础信息
     * @param externalData 扩展信息
     * @return createDataId
     */
    public static String createGEOData(CreateGEOData data, Map<Object, Object> externalData) {
        Map<Object, Object> parameters = JsonUtils.parse(JsonUtils.toJson(data), Map.class);
        parameters.putAll(externalData);
        String jsonResult = HttpUtils.post(createGEODataUrl, mapToURlFormat(parameters));
        JSONObject result = JsonUtils.parse(jsonResult, JSONObject.class);
        if (result.getInteger("status") != 0) {
            throw new RuntimeException(result.toString());
        }
        return result.getString("id");
    }

    /**
     * @param openId
     * @return JSONObject
     */
    public static JSONObject listGEOData(String openId) {
        Map map = new HashMap();
        map.put("ak", PropKit.get(AK));
        map.put("openId", openId);
        map.put("geotable_id", getTableId(WECHAT_TABLE_NAME));
        String jsonResult = HttpUtils.get(listGEODataUrl + "?" + mapToURlFormat(map));
        JSONObject result = JsonUtils.parse(jsonResult, JSONObject.class);
        if (result.getInteger("status") != 0) {
            throw new RuntimeException(result.toString());
        }
        return result;
    }

    public static String updatePOIData(CreateGEOData data, Map externalData) {
        Map<Object, Object> parameters = JsonUtils.parse(JsonUtils.toJson(data), Map.class);
        parameters.putAll(externalData);
        String jsonResult = HttpUtils.post(updateGEOColumnUrl, mapToURlFormat(parameters));
        JSONObject result = JsonUtils.parse(jsonResult, JSONObject.class);
        if (result.getInteger("status") != 0) {
            throw new RuntimeException(result.toString());
        }
        return result.getString("id");
    }

    public static JSONObject getRevertAddressByLocation(InLocationBean location) {
        Map<Object, Object> parameters = new HashMap<Object, Object>();
        parameters.put("ak", PropKit.get(AK));
        parameters.put("coordtype", "bd09ll");
        parameters.put("location", location.getLatitude() + "," + location.getLongitude());
        parameters.put("output", "json");
        parameters.put("pois", "0");
        String jsonResult = HttpUtils.post(revertGEOLocation, mapToURlFormat(parameters));
        JSONObject result = JsonUtils.parse(jsonResult, JSONObject.class);
        if (result.getInteger("status") != 0) {
            throw new RuntimeException(result.toString());
        }
        return result;
    }

    public static String objectToURlFormat(Object object) {
        String json = JsonUtils.toJson(object);
        return jsonToURLFormat(json);
    }

    public static String jsonToURLFormat(String json) {
        Map<Object, Object> queryParas = JsonUtils.parse(json, Map.class);
        return mapToURlFormat(queryParas);
    }

    public static String mapToURlFormat(Map<Object, Object> queryParas) {
        StringBuilder sb = new StringBuilder();
        boolean isFirst = true;
        for (Map.Entry<Object, Object> entry : queryParas.entrySet()) {
            if (isFirst) isFirst = false;
            else sb.append("&");
            String key = entry.getKey().toString();
            String value = entry.getValue() == null ? "" : entry.getValue().toString();
            if (StrKit.notBlank(value))
                try {
                    value = URLEncoder.encode(value, CHARSET);
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e);
                }
            sb.append(key).append("=").append(value);
        }
        return sb.toString();
    }


}
